import { IStream, IRenderedStream } from '../interface';
import StreamInfo from '../libs/StreamInfo';
import { isAgentStream, isAudioStream, isCustomerStream, isRecordHiddenScreenStream, isScreenStream, isTTSstream } from '../utils';

class MediaStreamDao {
	private renderedStreamMap: Map<string, IRenderedStream> = new Map();

	private clientsMap: Map<string, StreamInfo> = new Map();
	private agentStreams: IStream[] = [];
	private audioStreams: IStream[] = [];
	private customerStreams: IStream[] = [];
	private screenStreams: IStream[] = [];
	private recordStreams: IStream[] = [];
	private largeStreams: IStream[] = [];
	private allMediaStream: IStream[] = [];
	private TTSstream: IStream[] = [];
	private smallStreams: IStream[] = [];

	public setClientJoinSession(clientID: string, client: StreamInfo) {
		this.clientsMap.set(clientID, client);
	}

	public setClientLeaveSession(clientID: string) {
		if (this.clientExists(clientID)) {
			this.clientsMap.delete(clientID);
		}
	}

	public clientExists(clientID: string) {
		return this.clientsMap.has(clientID);
	}

	public findAllMediaStream(): IStream[] {
		return this.allMediaStream;
	}

	public findAllAgentStreams(): IStream[] {
		return this.agentStreams;
	}

	public findAllLargeStreams(): IStream[] {
		return this.largeStreams;
	}

	public findAllTTSstream(): IStream[] {
		return this.TTSstream;
	}

	public findAllSmallStreams(): IStream[] {
		return this.smallStreams;
	}

	public findAllRecordStreams(): IStream[] {
		return this.recordStreams;
	}

	public findAllScreenStreams(): IStream[] {
		return this.screenStreams;
	}

	public findAllAudioStreams(): IStream[] {
		return this.audioStreams;
	}

	public findAllCustomerStreams(): IStream[] {
		return this.customerStreams;
	}

	public findAllrenderedStream() {
		const streams = [...this.renderedStreamMap.values()];
		return streams;
	}

	public clearAllStream() {
		this.allMediaStream = [];
		this.updateStreams();
		this.clearRenderedStream();
	}

	public updateStreamByClientId(clientId: string, streamInfo: Pick<IStream, 'streamMode'>) {
		const stream = this.allMediaStream.find(item => item.clientId === clientId);
		if (!stream) return;
		const index = this.findIndex(stream);
		this.allMediaStream[index] = { ...stream, ...streamInfo };
	}

	public setRenderedStream(key: string, stream: MediaProvider) {
		let clientId = '';
		if (this.findStreamById(key)) {
			clientId = this.findStreamById(key)?.clientId || '';
		}
		this.renderedStreamMap.set(key, { clientId: clientId, stream: stream });

		console.log('renderedStreamMap:', this.renderedStreamMap);
	}

	public removeRenderedStream(key: string) {
		if (this.renderedStreamMap.has(key)) {
			this.renderedStreamMap.delete(key);
		}
	}

	public getRenderedStreamById(id: string) {
		if (this.renderedStreamMap.has(id)) {
			return this.renderedStreamMap.get(id);
		}
	}

	public setStreams(stream: IStream) {
		this.allMediaStream = [...this.allMediaStream, stream];
		this.updateStreams();
	}

	public isExists(label: string): boolean {
		const stream = this.allMediaStream.find(item => item.label === label);
		return stream ? true : false;
	}

	public findStreamById(label: string) {
		if (this.isExists(label)) {
			return this.allMediaStream.find(item => item.label === label);
		}
		return null;
	}

	public findIndex(stream: IStream) {
		let index = -1;
		for (let i = 0; i < this.allMediaStream.length; i++) {
			if (this.allMediaStream[i].id === stream.id) {
				index = i;
				break;
			}
		}
		return index;
	}

	public clearRenderedStream() {
		this.renderedStreamMap.clear();
	}

	public removeStreamByClientId(clientId: string): boolean {
		if (this.isClientExists(clientId)) {
			this.allMediaStream = this.allMediaStream.filter(item => item.clientId !== clientId);
			this.updateStreams();

			return true;
		}
		return false;
	}

	public removeStreamById(id: string): boolean {
		if (this.isExists(id)) {
			this.allMediaStream = this.allMediaStream.filter(item => item.id !== id);
			this.updateStreams();
			return true;
		} else if (this.isClientExists(id)) {
			this.updateStreams();
			return this.removeStreamByClientId(id);
		}
		if (this.renderedStreamMap.has(id)) {
			this.renderedStreamMap.delete(id);
		}
		return false;
	}

	private isClientExists(clientId: string) {
		const stream = this.allMediaStream.find(item => item.clientId === clientId);
		return stream ? true : false;
	}

	private updateStreams() {
		this.TTSstream = this.allMediaStream.filter(stream => isTTSstream(stream));
		this.agentStreams = this.allMediaStream.filter(stream => isAgentStream(stream));
		this.customerStreams = this.allMediaStream.filter(stream => isCustomerStream(stream));
		this.screenStreams = this.allMediaStream.filter(stream => isScreenStream(stream));
		this.audioStreams = this.allMediaStream.filter(stream => isAudioStream(stream));
		this.recordStreams = this.allMediaStream.filter(stream => isRecordHiddenScreenStream(stream));
		this.setLargeStreams();
		this.setSmallStreams();
		console.log('updateStreams:', this.allMediaStream);
	}

	/** 设置大窗口流 */
	private setLargeStreams() {
		// if (this.largeStreams.length !== 0) return;
		if (this.customerStreams.length === 0) {
			this.largeStreams = [];
		} else {
			this.largeStreams = [this.customerStreams[0]];
		}
		console.log(this.largeStreams, this.customerStreams, 'setLargeStreams');
	}

	/** 设置小窗口流 */
	private setSmallStreams() {
		const largeStream = this.largeStreams[0];
		if (largeStream) {
			this.smallStreams = this.allMediaStream.filter(stream => largeStream.clientId !== stream.clientId && !isRecordHiddenScreenStream(stream) && !isScreenStream(stream));
		} else {
			this.smallStreams = this.allMediaStream.filter(stream => !isRecordHiddenScreenStream(stream) && !isScreenStream(stream));
		}

		console.log('smallStreams:', this.smallStreams);
	}
}

export default MediaStreamDao;
